package cn.iocoder.yudao.module.pay.framework.impl.wallet;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.exception.Assertions;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.api.pay.order.dto.UnifiedOrderCreateDTO;
import cn.iocoder.yudao.module.api.pay.order.eums.UnifiedPayChannelEnum;
import cn.iocoder.yudao.module.api.pay.order.vo.UnifiedOrderVO;
import cn.iocoder.yudao.module.api.pay.refund.dto.UnifiedRefundCreateDTO;
import cn.iocoder.yudao.module.api.pay.refund.vo.UnifiedRefundVO;
import cn.iocoder.yudao.module.api.pay.transfer.dto.UnifiedTransferCreateDTO;
import cn.iocoder.yudao.module.api.pay.transfer.vo.UnifiedTransferVO;
import cn.iocoder.yudao.module.api.pay.wallet.enums.PayWalletBizTypeEnum;
import cn.iocoder.yudao.module.pay.framework.impl.AbstractPayClient;
import cn.iocoder.yudao.module.pay.framework.impl.NonePayClientConfig;
import cn.iocoder.yudao.module.pay.order.dal.dataobject.PayOrderDO;
import cn.iocoder.yudao.module.pay.order.service.PayOrderService;
import cn.iocoder.yudao.module.pay.refund.dal.dataobject.PayRefundDO;
import cn.iocoder.yudao.module.pay.refund.service.PayRefundService;
import cn.iocoder.yudao.module.pay.transfer.dal.dataobject.PayTransferDO;
import cn.iocoder.yudao.module.pay.transfer.service.PayTransferService;
import cn.iocoder.yudao.module.pay.wallet.dal.dataobject.PayWalletDO;
import cn.iocoder.yudao.module.pay.wallet.dal.dataobject.PayWalletTransactionDO;
import cn.iocoder.yudao.module.pay.wallet.service.PayWalletService;
import cn.iocoder.yudao.module.pay.wallet.service.PayWalletTransactionService;
import cn.iocoder.yudao.module.pay.wallet.vo.PayWalletTransactionRespVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.api.pay.ErrorCodeConstants.PAY_ORDER_NOT_FOUND;

/**
 * 钱包支付的 PayClient 实现类
 *
 * @author 山野羡民
 */
@Slf4j
public class WalletPayClient extends AbstractPayClient<NonePayClientConfig> {
    @Resource
    private PayWalletService payWalletService;
    @Resource
    private PayWalletTransactionService payWalletTransactionService;
    @Resource
    private PayOrderService payOrderService;
    @Resource
    private PayRefundService payRefundService;
    @Resource
    private PayTransferService payTransferService;

    public WalletPayClient(NonePayClientConfig config) {
        super(UnifiedPayChannelEnum.WALLET.getCode(), config);
    }

    @Override
    protected void doInit() {

    }

    @Override
    protected UnifiedOrderVO doUnifiedOrder(UnifiedOrderCreateDTO dto) {
        Long walletId = null;
        try {
            walletId = MapUtil.getLong(dto.getChannelExtras(), "wallet_id", null);
        } catch (Exception ignore) {
        }
        if (walletId == null || walletId <= 0) {
            Long userId = null;
            try {
                userId = MapUtil.getLong(dto.getChannelExtras(), "user_id", null);
            } catch (Exception ignore) {
            }
            Integer userType = null;
            try {
                userType = MapUtil.getInt(dto.getChannelExtras(), "user_type", null);
            } catch (Exception ignore) {
            }
            if (userId != null && userId > 0) {
                PayWalletDO wallet = payWalletService.getOrCreateWallet(userId, userType);
                if (wallet != null) {
                    walletId = wallet.getId();
                }
            }
        }
        Assertions.isTrue(walletId != null && walletId > 0, "余额支付失败：钱包不存在");
        PayWalletTransactionDO aDo = payWalletService.orderPay(walletId, dto.getPayNo(), dto.getPrice());
        return UnifiedOrderVO.successOf(aDo.getNo(), aDo.getCreator(), aDo.getCreateTime(), dto.getPayNo(), BeanUtils.toBean(aDo, PayWalletTransactionRespVO.class));
    }

    @Override
    protected UnifiedOrderVO doGetOrder(String payNo) {
        PayOrderDO orderDO = payOrderService.getOrderByNo(payNo);
        if (orderDO == null) {
            throw exception(PAY_ORDER_NOT_FOUND);
        }
        PayWalletTransactionDO aDo = payWalletTransactionService.getWalletTransaction(String.valueOf(orderDO.getId()), PayWalletBizTypeEnum.PAYMENT);
        if (aDo == null) {
            PayWalletDO wallet = payWalletService.getOrCreateWallet(NumberUtil.parseLong(orderDO.getCreator()), UserTypeEnum.MEMBER.getValue());
            aDo = payWalletService.orderPay(wallet.getId(), payNo, orderDO.getPrice());
        }
        return UnifiedOrderVO.successOf(aDo.getNo(), aDo.getCreator(), aDo.getCreateTime(), payNo, BeanUtils.toBean(aDo, PayWalletTransactionRespVO.class));
    }

    @Override
    protected UnifiedOrderVO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) {
        throw new UnsupportedOperationException("钱包支付无支付回调");
    }

    @Override
    protected boolean doCloseOrder(String payNo) throws Throwable {
        return true;
    }

    @Override
    protected UnifiedRefundVO doUnifiedRefund(UnifiedRefundCreateDTO dto) {
        PayRefundDO refundDO = payRefundService.getRefundByNo(dto.getRefundNo());
        Assertions.notNull(refundDO, "退款单不存在：" + dto.getRefundNo());
        PayWalletTransactionDO aDo = payWalletService.orderRefund(refundDO.getNo(), refundDO.getRefundPrice(), refundDO.getReason());
        return UnifiedRefundVO.successOf(aDo.getNo(), aDo.getCreateTime(), dto.getRefundNo(), BeanUtils.toBean(aDo, PayWalletTransactionRespVO.class));
    }

    @Override
    protected UnifiedRefundVO doGetRefund(String payNo, String refundNo) {
        PayRefundDO refundDO = payRefundService.getRefundByNo(refundNo);
        Assertions.notNull(refundDO, "退款单不存在：" + refundNo);
        PayWalletTransactionDO aDo = payWalletTransactionService.getWalletTransaction(String.valueOf(refundDO.getId()), PayWalletBizTypeEnum.PAYMENT_REFUND);
        if (aDo == null) {
            aDo = payWalletService.orderRefund(refundDO.getNo(), refundDO.getRefundPrice(), refundDO.getReason());
        }
        return UnifiedRefundVO.successOf(aDo.getNo(), aDo.getCreateTime(), refundNo, BeanUtils.toBean(aDo, PayWalletTransactionRespVO.class));
    }

    @Override
    protected UnifiedRefundVO doParseRefundNotify(Map<String, String> params, String body, Map<String, String> headers) {
        throw new UnsupportedOperationException("钱包支付无退款回调");
    }

    @Override
    protected UnifiedTransferVO doUnifiedTransfer(UnifiedTransferCreateDTO dto) {
        PayTransferDO transferDO = payTransferService.getTransferByNo(dto.getTransferNo());
        Assertions.notNull(transferDO, "转账单不存在：" + dto.getTransferNo());
        PayWalletTransactionDO aDo = payWalletService.orderTransfer(transferDO.getTransferNo(), transferDO.getPrice(), transferDO.getSubject());
        return UnifiedTransferVO.successOf(aDo.getNo(), aDo.getCreateTime(), dto.getTransferNo(), BeanUtils.toBean(aDo, PayWalletTransactionRespVO.class));
    }

    @Override
    protected UnifiedTransferVO doGetTransfer(String transferNo) {
        PayTransferDO transferDO = payTransferService.getTransferByNo(transferNo);
        PayWalletTransactionDO aDo = payWalletTransactionService.getWalletTransaction(String.valueOf(transferDO.getId()), PayWalletBizTypeEnum.TRANSFER);
        if (aDo == null) {
            aDo = payWalletService.orderTransfer(transferNo, transferDO.getPrice(), transferDO.getSubject());
        }
        return UnifiedTransferVO.successOf(aDo.getNo(), aDo.getCreateTime(), transferNo, BeanUtils.toBean(aDo, PayWalletTransactionRespVO.class));
    }

    @Override
    protected UnifiedTransferVO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) {
        throw new UnsupportedOperationException("钱包支付无转账回调");
    }

}
